RadioManager = {
    C_EVENT_RADIO_USER_REMOVED = 'C_EVENT_RADIO_USER_REMOVED',
}

--[[
    TODO:
    从mission文件中提前录入被预设好的无线电, 并且登记单位.
    完善事件触发驱动的info更新机

]]

do
    --================== Config ==================
    local Debug = false

    local Mhz = 1000000
    local UnknownUserIndex = 1

    local DrawMapInfo = true
    local DrawInfoID = nil

    local DrawInfoCoord = {
        x=-289782,
        y=1000,
        z=316349,
    }

    local theatre = env.mission.theatre
    if theatre == 'GermanyCW' then
        DrawInfoCoord = {
            x=5152,
            y=1000,
            z=-746539,
        }
    end


    local FrequencyType = {
        UHF = 'UHF',
        VHF = 'VHF',
    }

    local Modulation = {
        AM = radio.modulation.AM,
        FM = radio.modulation.FM,
    }

    local DEFAULT_PUBLIC_FREQ = {
        [FrequencyType.UHF] = 251, --Mhz
        [FrequencyType.VHF] = 130, --Mhz
    }
    
    local ChannelInterval = 0.05 --Mhz
    local FREQUENCY_RANGE = {
        [FrequencyType.UHF] = {
            min = 225, --Mhz
            max = 399.97 --Mhz
        },
        [FrequencyType.VHF] = {
            min = 30, --Mhz
            max = 159.950, --Mhz
        },
    }

    local RADIO_USER_REMOVE_EVENT_FORM = {
        id = RadioManager.C_EVENT_RADIO_USER_REMOVED,
        time = nil,
        userName = nil
    }

    --================ Config end ================

    local AllChannels = {
        [DEFAULT_PUBLIC_FREQ[FrequencyType.UHF]] = {
            users = {},
            reusable = true,
        },
        [DEFAULT_PUBLIC_FREQ[FrequencyType.VHF]] = {
            users = {},
            reusable = true,
        },
    }
    
    local EventHandlerPool = {}
    local RegisteredUsers = {}

    --- table深度复制
	-- Usually this object is a table.
	-- See also: from http://lua-users.org/wiki/CopyTable
	-- @param object object to copy
	-- @return copy of object
    local function deepCopy(object)
		local lookup_table = {}
		local function _copy(object)
			if type(object) ~= "table" then
				return object
			elseif lookup_table[object] then
				return lookup_table[object]
			end
			local new_table = {}
			lookup_table[object] = new_table
			for index, value in pairs(object) do
				new_table[_copy(index)] = _copy(value)
			end
			return setmetatable(new_table, getmetatable(object))
		end
		return _copy(object)
	end

    -- 判断频道所属范围
    local function getFrequencyType(freq)
        if not freq or type(freq)~='number' then 
            return FrequencyType.UHF 
        end
        
        local freqType = FrequencyType.UHF
        if freq >= FREQUENCY_RANGE[freqType].min then
            return freqType
        end

        return FrequencyType.VHF
    end

    -- 检查频率是否在有效范围内
    local function isFrequencyValid(freq, freqType)
        if not freq or type(freq)~='number' then 
            return false 
        end

        freqType = freqType or getFrequencyType(freq)

        local range = FREQUENCY_RANGE[freqType]
        return freq >= range.min and freq <= range.max
    end

    -- 获取默认频道
    local function getDefaultChannel(freqType)
        return DEFAULT_PUBLIC_FREQ[freqType]
    end

    -- 获取一个可用频道
    local function getAvailableChannel(freq,reusable)
        local freqType = getFrequencyType(freq)

        -- 若freq合法
        if isFrequencyValid(freq,freqType) then
            if not AllChannels[freq] then return freq end
            if reusable then
                return freq 
            end
        end

        -- 若freq不合法
        for i=FREQUENCY_RANGE[freqType].min*Mhz,FREQUENCY_RANGE[freqType].max*Mhz,ChannelInterval*Mhz do
            local tempFreq = i/Mhz
            
            if not AllChannels[tempFreq] then
                return tempFreq
            end

            if reusable and AllChannels[tempFreq].reusable then
                return tempFreq
            end
        end
        
        return getDefaultChannel(freqType)
    end

    -- 获取 "无线电用户被移除" 事件格式
    function RadioManager.getRadioUserRemovedEventForm(time,userName)
        local form = deepCopy(RADIO_USER_REMOVE_EVENT_FORM)
        form.time = time
        form.userName = userName
        return form
    end

    -- 将频道设置为可以多人使用
    function RadioManager.setReusable(freq)
        if not freq or type(freq) ~= 'number' or not AllChannels[freq] then
            return 
        end

        AllChannels[freq].reusable = true
    end

    --@param table userName freq modulation reusable
    function RadioManager.registerChannel(params)
        local userName = params.userName
        local freq = params.freq
        local modulation = params.modulation or Modulation.AM
        local reusable = params.reusable

        -- 检查 userName
        if not userName or type(userName)~='string' then
            userName = 'UnknowUser-'..UnknownUserIndex
            UnknownUserIndex = UnknownUserIndex + 1
        end
        
        -- 规范 reusable
        if reusable then reusable = true end

        -- 强制注销旧频道（若存在）
        local registeredFreq = RadioManager.getUserFrequency(userName)
        if registeredFreq then
            --如果重复申请就返回
            if registeredFreq == freq then return freq*Mhz end

            RadioManager.deregisterChannel(userName)
        end
        
        local newFreq = getAvailableChannel(freq,reusable)
        if newFreq ~= freq then
            freq = freq or 'Null'

            local errMsg = 'RadioManager - registerChannel: ['..userName..': '..freq..'Mhz] Input frequency error, set to new channel: '

            if Localizations then
                errMsg = 'RadioManager - registerChannel: ['..userName..': '..freq..'Mhz] '
                errMsg = errMsg .. Localizations:translate('Input frequency error, set to new channel: ', 'cn')
            end

            errMsg = errMsg .. newFreq

            if Debug then
                Utils.Debug(errMsg)
            end
        end
        freq = newFreq
        
        if Debug then
            Utils.Debug('RadioManager - registerChannel: '..freq..' for '..userName)
        end

        AllChannels[freq] = AllChannels[freq] or {users = {}}
        table.insert(AllChannels[freq].users,userName)
        AllChannels[freq].reusable = reusable
        AllChannels[freq].modulation = modulation

        RegisteredUsers[userName] = {
            freq = freq, 
            modulation = modulation
        }

        -- 添加单位移除的事件监听器
        if world then
            local oldHandler = EventHandlerPool[userName]
            if oldHandler then
                world.removeEventHandler(oldHandler)
            end

            local ev = {
                userName = userName,
            }
            function ev:onEvent(event)
                if event.id == world.event.S_EVENT_DEAD then
                    local obj = event.initiator
                    if not obj or not obj.getName or not  obj.getGroup then return end

                    if Group.getByName(ev.userName) then
                        if obj.getGroup then
                            obj = obj:getGroup()
                        end
                    else
                        world.removeEventHandler(self)
                        RadioManager.deregisterChannel(self.userName)
                        return
                    end
                    if not obj then return end
                    
                    local objName = obj:getName()

                    if objName == self.userName then
                        
                        if Debug then
                            local msg = 'RadioManager - [Dead] event for: '..self.userName..' deregistering...'
                            Utils.Debug(msg)
                            env.info(msg)
                        end

                        world.removeEventHandler(self)
                        RadioManager.deregisterChannel(self.userName)
                    end
                end

                -- 通过 C_EVENT_RADIO_USER_REMOVED 事件触发注销
                if event.id == RadioManager.C_EVENT_RADIO_USER_REMOVED then
                    if not event.userName then return end

                    if event.userName == self.userName then
                        if Debug then
                            local msg = 'RadioManager - [Radio user removed] event for: '..self.userName..' deregistering...'
                            Utils.Debug(msg)
                            log.info(msg)
                        end

                        RadioManager.deregisterChannel(self.userName)
                    end
                end
            end

            world.addEventHandler(ev)
            EventHandlerPool[userName] = ev
        end

        RadioManager.DrawInfo()

        return freq*Mhz
    end

    function RadioManager.deregisterChannel(userName)
        if not userName or type(userName) ~= 'string' then
            return false
        end

        local freq = RadioManager.getUserFrequency(userName)

        if AllChannels[freq] then
            if AllChannels[freq] then
                local users = AllChannels[freq].users
                for i, name in ipairs(users) do
                    if name == userName then

                        if Debug then
                            Utils.Debug('TACANManager - deregisterChannel: '..freq..' for '..userName)
                        end

                        local eventHandler = EventHandlerPool[userName]
                        if eventHandler then
                            world.removeEventHandler(eventHandler)
                            EventHandlerPool[userName] = nil
                            eventHandler = nil
                        end
                        RegisteredUsers[userName] = nil
                        
                        table.remove(users, i)
                        if #users == 0 then
                            AllChannels[freq] = nil
                        end

                        RadioManager.DrawInfo()

                        return true
                    end
                end
            end
        end

        return false
    end

    --- 提供私有参数访问接口(只读)
    -- @param string FrequencyType 'UHF'/'VHF'
    -- @return number/nil the public frequency ex: 251.250(Mhz)
    function RadioManager.getDefaultPublicFreq(freqType)
        if not freqType then return end
        if type(freqType)~='string' then return end
        
        return DEFAULT_PUBLIC_FREQ[freqType]
    end

    -- @return table RadioManager.FrequencyType = {'UHF','VHF'}
    function RadioManager.getFrequencyTypeTable()

        return deepCopy(FrequencyType)
    end

    ---@param userName string -- User name of registered user.
    ---@return table|nil of user's frequency.
    function RadioManager.getUserFrequency(userName)
        if not userName or type(userName)~='string' then return nil end

        if RegisteredUsers[userName] then
            return RegisteredUsers[userName].freq
        end

        return nil
    end

    ---获取已注册的用户信息(频率和模式)
    ---@param userName string -- User name of registered user.
    ---@return table freq and modulation of this user if registered. 
    function RadioManager.getRegisteredUser(userName)
        if not userName then return end
        if type(userName)~='string' then return end

        return RegisteredUsers[userName]
    end
    
    ---@return table of all registered users with frequencies
    function RadioManager.getRegisteredUsers()
        
        return deepCopy(RegisteredUsers)
    end

    ---@param freq number -- freq in "Mhz" of the radio.
    ---@return table the public frequency, ex: 251.250(Mhz)
    function RadioManager.getChannelDataByFrequency(freq)
        if not freq or type(freq)~='number' then return nil end

        return deepCopy(AllChannels[freq])
    end

    -- @return table of all registered channels
    function RadioManager.getAllChannels()
        
        return deepCopy(AllChannels)
    end

    -- @return boolean, if the Debug mode is on
    function RadioManager.isDebugMode()
        return Debug
    end

    ---Get radio info.
    ---@return string formatted info string for all registered channel.
    function RadioManager.getInfo()

        local modulationText = {
            [Modulation.AM] = 'AM',
            [Modulation.FM] = 'FM',
        }

        -- 提取已经注册的用户名[userName]
        local userNames = {}
        for userName, data in pairs(RegisteredUsers) do
            table.insert(userNames,userName)
        end
        --对 userNames 排序
        table.sort(userNames,function (a,b)
            return string.upper(a) < string.upper(b)
        end)

        -- 创建输出信息
        local info = ' Radio:'
        for i=1,#userNames,1 do
            local userName = userNames[i]
            local data = RegisteredUsers[userName]
            if not data then break end
            
            info = info..'\n '..userName..': '..data.freq..' Mhz.['..modulationText[data.modulation]..'] '
        end
        
        return info
    end

    --- Draw radio info on F10 map.
    function RadioManager.DrawInfo()
        if not DrawMapInfo then return end

        local info = RadioManager.getInfo()

        if not DrawInfoID then
            DrawInfoID = Utils.getMarkupID()
            trigger.action.textToAll(coalition.side.BLUE,DrawInfoID,DrawInfoCoord,{1,1,0,1},{0,0,0,0.3},12,false,info)
            -- trigger.action.markupToAll(5,DrawInfoID,coalition.side.BLUE,DrawInfoCoord,{text = info},{1,0,0,1},{1,1,0,1},1)
            return
        end

        trigger.action.setMarkupText(DrawInfoID,info)
    end
end

--Debug funcs
local function debugFuncs(vars)
    RadioManager.registerChannel(vars)

    local keys = {}
    local allChannels= RadioManager.getAllChannels()
    for k, v in pairs(allChannels) do
        table.insert(keys, k)
    end
    table.sort(keys, function(a, b)
        return a > b
    end)

    local function getChannelMsg(frequency)
        local msg = ''
        local data = allChannels[frequency]
        msg = msg..'\n===== '..frequency..' Mhz =====\n'
        for i,name in ipairs(data.users) do
            msg = msg..' '..i..'.'..name..' '
        end

        local reusable_msg = 'false'
        if data.reusable then
            reusable_msg = 'true'
        end

        msg = msg..'\n reusable: '..reusable_msg
        return msg
    end
    
    local defaultPublicChannel_UHF = RadioManager.getDefaultPublicFreq('UHF')
    local defaultPublicChannel_VHF = RadioManager.getDefaultPublicFreq('VHF')
    
    local text = getChannelMsg(defaultPublicChannel_UHF)
    text = text.. getChannelMsg(defaultPublicChannel_VHF)

    for _, tFreq in pairs(keys) do
        if tFreq ~= defaultPublicChannel_UHF and tFreq ~= defaultPublicChannel_VHF then
            text = text.. getChannelMsg(tFreq)
        end
    end

    if Utils and Utils.Debug then
        Utils.Debug(text)
    end

    if log then
        log.info(text)
    end

    print(text)
end

local autoGenData = false
if autoGenData then
    local testIndex = 1
    local lastUserName = nil

    if timer then
        timer.scheduleFunction(function (vars,time)
            local vars = {}
            local repeatTime = math.random(5,20)

            vars.userName = 'ts'..testIndex
            if math.random(1,10)>7 then
                vars.userName = nil
            end 
            if vars.userName then
                if math.random(1,10)>4 and lastUserName then
                    vars.userName = lastUserName
                end
                if vars.userName~=lastUserName then
                    testIndex = testIndex + 1
                end
                lastUserName = vars.userName
            end

            vars.freq = math.random(10,410)
            if math.random(1,10)>7 then
                vars.freq = nil
            end

            vars.reusable = false
            if math.random(1,10)>7 then
                vars.reusable = true
            end

            debugFuncs(vars)
            
            return time + repeatTime
        end,{},timer.getTime()+5)
    end
end
--Debug funcs